home *** CD-ROM | disk | FTP | other *** search
- /*++
- /* NAME
- /* gphys 3
- /* SUMMARY
- /* g protocol packet input/output
- /* PROJECT
- /* pc-mail
- /* PACKAGE
- /* cico
- /* SYNOPSIS
- /* #include "gp.h"
- /*
- /* void gsctrl(fd,c)
- /* int fd,c;
- /*
- /* void gsdata(fd,pk,c)
- /* int fd,c;
- /* Packet *pk;
- /*
- /* int grpack(fd,pk)
- /* int fd;
- /* Packet *pk;
- /* DESCRIPTION
- /* The functions in this module send and receive packets. Interfacing
- /* is based on Packet structures. Messages are interpreted elsewhere.
- /*
- /* gsctrl() sends a control packet to the remote receiver (no data
- /* segment).
- /*
- /* gsdata() sends a data packet to the remote receiver.
- /* The Packet structure is completed with a 16-bit checksum.
- /* This function expects read/write sequence information in
- /* the c parameter.
- /*
- /* grpack() receives a packet from the remote transmitter and checks
- /* its integrity. It fills in the k, c, len and check fields of the
- /* Packet structure and returns the type of message (DATA, SHORT,
- /* CLOSE, RJ, RR, etcetera).
- /* DIAGNOSTICS
- /* grpack() returns FAIL if a corrupted packet was received, and
- /* TIME if no packet was received within the time-out interval.
- /* BUGS
- /* No data re-reading in case of transmission errors.
- /* Some parts of the code rely on 8-bit bytes, 16-bit short integers.
- /* AUTHOR(S)
- /* W.Z. Venema
- /* Eindhoven University of Technology
- /* Department of Mathematics and Computer Science
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- /* CREATION DATE
- /* Sun Apr 19 11:39:27 GMT+1:00 1987
- /* LAST MODIFICATION
- /* 90/01/22 13:01:42
- /* VERSION/RELEASE
- /* 2.1
- /*--*/
-
- #include <signal.h>
- #include <setjmp.h>
- #include "gp.h"
-
- /* local and forward declarations */
-
- static jmp_buf timebuf;
- static int chksum(),readhead(),readdata(),clkint();
-
- #define READ(fd,cp,n) { if (read(fd,cp,n) != n) clkint(); }
-
- /*
- * "A six byte framing envelope is constructed using the control"
- * "byte C of a packet and five other bytes as depicted below."
- * <DLE><k><c0><c1><C><x>
- * "The <DLE> symbol denotes the ASCII ctrl/P character. If the"
- * "envelope is to be followed by a data segment, <k> has the"
- * "value log2(size)-4; i.e. 1 <= k < 8. If k is 9, then the"
- * "envelope represents a control packet. The <c0> and <c1>"
- * "bytes are the low-order and high-order bytes respectively of"
- * "0xAAA minus a 16-bit checksum. For control packets, this"
- * "16-bit checksum is the same as the control byte C. For data"
- * "packets, the checksum is calculated by the program below."
- * "The <x> byte is the exclusive-or of <k><c0><c1><C>. Error"
- * "control is accomplished by checking a received framing"
- * "envelope for compliance with the definition, and comparing a"
- * "checksum function of the data segment with <c0><c1>."
- */
-
- /* gsctrl - send control packet (no data segment) */
-
- void gsctrl(fd,c)
- int fd,c;
- {
- char header[6];
- register char chkhdr;
- register char *cp = header;
- int cksm = MAGIC-c; /* do checksum */
-
- *cp++ = CTRL('P'); /* start of header */
- chkhdr = *cp++ = KCTRL; /* k byte (control) */
- chkhdr ^= *cp++ = cksm; /* c0 byte (checksum lsb) */
- chkhdr ^= *cp++ = cksm>>8; /* c1 byte (checksum msb) */
- chkhdr ^= *cp++ = c; /* message|sequence info */
- *cp = chkhdr; /* header checksum */
-
- write(fd,header,sizeof(header)); /* send header */
- DEBUG(9,"xmt: %o\n",c&0377); /* show header */
- }
-
- /* gsdata - send data packet */
-
- void gsdata(fd,pk,c)
- int fd,c;
- register Packet *pk;
- {
- char header[6];
- register char chkhdr;
- register char *cp = header;
- int cval = pk->c|(c&077); /* fold in sequence info */
-
- pk->chk = MAGIC-(chksum(pk->data,pk->len)^(0377&cval));
-
- *cp++ = CTRL('P'); /* start of header */
- chkhdr = *cp++ = pk->k; /* k byte (message length) */
- chkhdr ^= *cp++ = pk->chk; /* c0 byte (checksum lsb) */
- chkhdr ^= *cp++ = pk->chk>>8; /* c1 byte (checksum msb) */
- chkhdr ^= *cp++ = cval; /* data|sequence info */
- *cp = chkhdr; /* header checksum */
-
- write(fd,header,sizeof(header)); /* send header */
- DEBUG(9,"xmt: %o\n",cval&0377); /* show header */
-
- write(fd,pk->data,pk->len); /* send data segment */
- DEBUG(9,"xmt: data %d bytes\n",pk->segl); /* show data */
- }
-
- /* grpack - receive one data or control packet; return packet type info */
-
- int grpack(fd,pk)
- int fd;
- register Packet *pk;
- {
- if (setjmp(timebuf)) /* in case we time out */
- return(TIME); /* it just happened */
- signal(SIGALRM,clkint); /* alarm clock response */
- alarm(ALARM); /* set alarm clock */
-
- if (readhead(fd,pk)) { /* read packet header */
- DEBUG(7,"rcv: bad header\n","");
- alarm(0); /* turn timer off */
- return(FAIL); /* header checksum error */
- } else if (pk->k == KCTRL) {
- alarm(0); /* turn timer off */
- return(MESG(pk->c)); /* CLOSE | RJ | RR etcetera */
- } else if (readdata(fd,pk)) {
- DEBUG(7,"rcv: bad data\n","");
- alarm(0); /* turn timer off */
- return(FAIL); /* data checksum error */
- } else {
- alarm(0); /* turn timer off */
- return(TYPE(pk->c)); /* DATA | SHORT */
- }
- }
-
- /* readhead - read header and check header checksum */
-
- static int readhead(fd,pk)
- int fd;
- register Packet *pk;
- {
- char header[5];
- int ok;
- register char chkhdr;
- register char *cp = header;
-
- do { /* start reading */
- READ(fd,cp,1); /* skip all garbage */
- } while (*cp != CTRL('P')); /* up to packet header */
-
- READ(fd,header,sizeof(header)); /* read packet header */
-
- chkhdr = pk->k = *cp++; /* data length or control */
- chkhdr ^= pk->chk = *cp++&0377; /* data checksum lsb */
- chkhdr ^= *cp;
- pk->chk |= (*cp++&0377)<<8; /* data checksum msb */
- chkhdr ^= pk->c = *cp++; /* control packet or data */
- if (ok = (chkhdr == *cp))
- DEBUG(9,"rcv: %o\n",pk->c&0377);
- return(!ok); /* check the checksum */
- }
-
- /* readdata - read data segment and check data checksum */
-
- static int readdata(fd,pk)
- int fd;
- register Packet *pk;
- {
- if (seglen[pk->k] > pk->len) {
- DEBUG(7,"rcv: data %d bytes too big\n",seglen[pk->k]);
- return(1);
- } else {
- register int i;
- DEBUG(9,"rcv: data %d bytes\n",pk->len = seglen[pk->k]);
- for (i = 0; i < pk->len; i++) {
- READ(fd,&pk->data[i],1);
- }
- return(pk->chk+(chksum(pk->data,pk->len)^(pk->c&0377)) != MAGIC);
- }
- }
-
- /* clkint - tiny time-out routine */
-
- static int clkint()
- {
- DEBUG(9,"rcv: timed out\n","");
- longjmp(timebuf,1);
- /* NOTREACHED */
- }
-
- /* chksum - unix packet driver checksum algorithm */
-
- static int chksum(s,n)
- register char *s;
- register n;
- {
- register short sum;
- register unsigned short t;
- register short x;
-
- sum = -1;
- x = 0;
- do {
- if (sum < 0) {
- sum <<= 1;
- sum++;
- } else
- sum <<= 1;
- t = sum;
- sum += (unsigned)*s++ & 0377;
- x += sum ^ n;
- if ((unsigned short)sum <= t) {
- sum ^= x;
- }
- } while (--n > 0);
-
- return(sum);
- }
-